#include "sweSolver_valuesTestFunctions.hpp"
#include "blockwiseIntegrated.hpp"
#include "timeMarchingLoop.hpp"

#include <catch2/catch_test_macros.hpp>

TEST_CASE("Value test: v-shaped domain", "[value]"){

	auto test = [](const auto& dummyMesh){
		using MeshType = remove_qualifiers<decltype(dummyMesh)>;
		auto mesh { vShapedDomain_mesh<MeshType>() };
		mesh.logger().debug(
			"Running block-wise value test on type {}",
			type_name<MeshType>()
		);
		Time time;
		SWESolver solver {mesh, time};
		auto& settings { solver.settings() };
		vShapedDomain_settings(solver, time);

		// omp_set_num_threads(1);

		SECTION("Conventional loop"){
			marchingLoop::basic(solver, time, [](){});
			vShapedDomain_checkResults(solver);
		}
		SECTION("Block-wise integrated loop"){
			settings.useIntegratedBlockLoop = true;
			settings.blocksizeX = 8;
			settings.blocksizeY = 2;

			swe::integratedTimeLoop(
				solver, time, [](){} // empty exporter
			);
			vShapedDomain_checkResults(solver);
		}
		SECTION("Cell-wise integrated loop"){
			// omp_set_num_threads(1);
			settings.useIntegratedBlockLoop = true;
			settings.blocksizeX = 1;
			settings.blocksizeY = 1;

			swe::integratedTimeLoop(
				solver, time, [](){} // empty exporter
			);
			vShapedDomain_checkResults(solver);
		}

	};
	SECTION("UniMesh"){
		test( UniMesh{} );
	}
	SECTION("RectMesh"){
		test( RectMesh{} );
	}
}

TEST_CASE("Value test: Dam break", "[value],[slow]"){
	// hms::log::getLogger()->set_level(hms::log::Level::debug);


	auto test = [](const auto& dummyMesh, bool useFriction){
		using MeshType = remove_qualifiers<decltype(dummyMesh)>;

		Time time;
		auto mesh { dambreakTest_mesh<MeshType>() };
		mesh.logger().debug(
			"Running SWE solver dambreak test on type {}",
			type_name<MeshType>()
		);
		SWESolver solver { mesh, time };
		dambreakTest_settings(solver, time, useFriction);
		
		// omp_set_num_threads(1);

		// std::cout
		// 	<< "MeshType=" << type_name<MeshType>()
		// 	<< ", useFriction=" << std::boolalpha << useFriction;

		SECTION("Conventional"){
			// std::cout << ", conventional\n";
			marchingLoop::basic(solver, time, [](){});
			dambreakTest_checkResults(solver, useFriction);
		}
		SECTION("Block-wise"){
			// std::cout << ", block-wise\n";
			auto& settings { solver.settings() };
			settings.useIntegratedBlockLoop = true;
			settings.blocksizeX = 4;
			settings.blocksizeY = 4;
			swe::integratedTimeLoop(
				solver, time, [](){} // empty exporter
			);
			dambreakTest_checkResults(solver, useFriction);
		}
		SECTION("Cell-wise"){
			// omp_set_num_threads(1);
			// std::cout << ", cell-wise\n";
			auto& settings { solver.settings() };
			settings.useIntegratedBlockLoop = true;
			settings.blocksizeX = 1;
			settings.blocksizeY = 1;
			swe::integratedTimeLoop(
				solver, time, [](){} // empty exporter
			);
			dambreakTest_checkResults(solver, useFriction);
		}
	};
	SECTION("no friction"){
		SECTION("UniMesh"){
			test(  UniMesh{}, false );
		}
		SECTION("RectMesh"){
			test( RectMesh{}, false );
		}
	}
	SECTION("with friction"){
		SECTION("UniMesh"){
			test(  UniMesh{}, true );
		}
		SECTION("RectMesh"){
			test( RectMesh{}, true );
		}
	}
}